class MysqlStatement {
    constructor(...tbs) {
        this.clear(false);
        this.table(...tbs);
    }
    static find(...tbs) {
        return new MysqlStatement(...tbs);
    }
    table(...tbs) {
        if (tbs.length) {
            this.tableArr = [];
            for (let i = 0; i < tbs.length; i++) {
                if (tbs[i] && tbs[i].length) {
                    this.tableArr.push(tbs[i]);
                }
            }
        }
        return this;
    }
    filed(...fileds) {
        if (fileds.length) {
            for (let i = 0; i < fileds.length; i++) {
                if (fileds[i] && fileds[i].length) {
                    if (this.filedArr) {
                        this.filedArr.push(fileds[i]);
                    } else {
                        this.filedArr = [fileds[i]];
                    }
                }
            }
        }
        return this;
    }
    foundRows() {
        this.foundRowsStr = ' SQL_CALC_FOUND_ROWS';
        return this;
    }
    set(obj) {
        if (obj) {
            const ks = Object.keys(obj);
            for (let i = 0; i < ks.length; i++) {
                if (this.setStr) {
                    this.setStr.push(`${ks[i]}=${obj[ks[i]]}`);
                } else {
                    this.setStr = [`${ks[i]}=${obj[ks[i]]}`];
                }
            }
        }
        return this; 
    }
    where(...condition) {
        if (condition.length) {
            for (let i = 0; i < condition.length; i++) {
                if (condition[i] && condition[i].length) {
                    if (this.whereArr) {
                        this.whereArr.push(condition[i]);
                    } else {
                        this.whereArr = [condition[i]];
                    }
                }
            }
        }
        return this;
    }
    join(table, ...on) {
        let str = `INNER JOIN ${table}`;
        if (on.length) {
            str += ` ON ${on.join(' AND ')}`;
        }
        if (this.joinArr) {
            this.joinArr.push(str);
        } else {
            this.joinArr = [str];
        }
        return this;
    }
    leftJoin(table, ...on) {
        let str = `LEFT JOIN ${table}`;
        if (on.length) {
            str += ` ON ${on.join(' AND ')}`;
        }
        if (this.joinArr) {
            this.joinArr.push(str);
        } else {
            this.joinArr = [str];
        }
        return this;
    }
    rightJoin(table, ...on) {
        let str = `RIGHT JOIN ${table}`;
        if (on.length) {
            str += ` ON ${on.join(' AND ')}`;
        }
        if (this.joinArr) {
            this.joinArr.push(str);
        } else {
            this.joinArr = [str];
        }
        return this;
    }
    groupBy(...condition) {
        if (condition.length) {
            this.groupArr = [];
            for (let i = 0; i < condition.length; i++) {
                if (condition[i] && condition[i].length) {
                    this.groupArr.push(condition[i]);
                }
            }
        }
        return this;
    }
    orderBy(...condition) {
        if (condition.length) {
            this.orderArr = [];
            for (let i = 0; i < condition.length; i++) {
                if (condition[i] && condition[i].length) {
                    this.orderArr.push(condition[i]);
                }
            }
        }
        return this;
    }
    desc(desc=true) {
        this.isDesc = desc;
        return this;
    }
    limit(rows, begin=null) {
        this.limitStr = ` LIMIT ${begin?(begin+','):''}${rows}`;
        return this;
    }
    page(page, rows) {
        this.limitStr = ` LIMIT ${page*rows},${rows}`;
        return this;
    }
    values(obj) {
        if (obj) {
            const ks = Object.keys(obj);
            for (let i = 0; i < ks.length; i++) {
                if (this.filedArr) {
                    this.filedArr.push(ks[i]);
                } else {
                    this.filedArr = [ks[i]];
                }
                if (this.valuesStr) {
                    this.valuesStr.push(obj[ks[i]]);
                } else {
                    this.valuesStr = [obj[ks[i]]];
                }
            }
        }
        return this; 
    }
    select(rows=null) {
        let ret = null;
        if (this.filedArr && this.filedArr.length) {
            ret = `SELECT${this.foundRowsStr?this.foundRowsStr:''} ${this.filedArr.join(',')} FROM `;
        } else {
            ret = `SELECT${this.foundRowsStr?this.foundRowsStr:''} * FROM `;
        }
        ret += this.tableArr.join(',');
        if (this.joinArr) {
            ret += ` ${this.joinArr.join(' ')}`;
        }
        if (this.whereArr && this.whereArr.length) {
            ret += ` WHERE ${this.whereArr.join(' AND ')}`;
        }
        if (this.groupArr && this.groupArr.length) {
            ret += ` GROUP BY ${this.groupArr.join(',')}`;
        }
        if (this.orderArr && this.orderArr.length) {
            ret += ` ORDER BY ${this.orderArr.join(',')}`;
            if (this.isDesc) {
                ret += ' DESC';
            }
        }
        if (this.limitStr) {
            ret += this.limitStr;
        } else if (rows) {
            ret += ` LIMIT ${rows}`;
        }
        return ret+';';
    }
    update(rows=null) {
        let ret = `UPDATE ${this.tableArr.join(',')} SET ${this.setStr.join(',')}`;
        if (this.whereArr) {
            ret += ` WHERE ${this.whereArr.join(' AND ')}`;
        }
        if (this.limitStr) {
            ret += this.limitStr;
        } else if (rows) {
            ret += ` LIMIT ${rows}`;
        }
        return ret+';';
    }
    delete(rows=null) {
        let ret = `DELETE FROM ${this.tableArr.join(',')}`;
        if (this.whereArr) {
            ret += ` WHERE ${this.whereArr.join(' AND ')}`;
        }
        if (this.limitStr) {
            ret += this.limitStr;
        } else if (rows) {
            ret += ` LIMIT ${rows}`;
        }
        return ret+';';
    }
    insert(ignore=false) {
        let ret = `INSERT ${ignore?'IGNORE ':''}INTO ${this.tableArr[0]}`;
        if (this.filedArr) {
            ret += `(${this.filedArr.join(',')})`;
        }
        if (this.valuesStr) {
            ret += ` VALUES(${this.valuesStr.join(',')})`;
        }
        return ret+';';
    }
    duplicate() {
        let ret = `INSERT INTO ${this.tableArr[0]}`;
        if (this.filedArr) {
            ret += `(${this.filedArr.join(',')})`;
        }
        if (this.valuesStr) {
            ret += ` VALUES(${this.valuesStr.join(',')})`;
        }
        if (this.setStr) {
            ret += ` ON DUPLICATE KEY UPDATE ${this.setStr.join(',')}`;
        }
        return ret+';';
    }
    truncate() {
        let ret = `TRUNCATE TABLE ${this.tableArr.join(',')};`;
        return ret;
    }
    drop() {
        let ret = `DROP TABLE ${this.tableArr.join(',')};`;
        return ret;
    }
    clear(exceptTable=false) {
        if (!exceptTable) {
            this.tableArr = null;
        }
        this.whereArr = null;
        this.filedArr = null;
        this.joinArr = null;
        this.groupArr = null;
        this.orderArr = null;
        this.isDesc = false;
        this.limitStr = null;
        this.valuesStr = null;
        this.setStr = null;
        this.foundRowsStr = null;
    }
}

module.exports = MysqlStatement;
